package com.pkk.alert.web.config.properties;


import static com.pkk.alert.web.config.config.ScheduleConfig.APPLICATIONCONTEXT;

import com.alibaba.fastjson.JSONObject;
import java.lang.reflect.Method;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.support.CronSequenceGenerator;

/**
 * 定时任务的基础信息
 *
 * @author peikunkun
 * @version V1.0
 * @date 2020-11-03 15:18
 **/
@Data
@Slf4j
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ScheduleInfo {

  /**
   * 任务名称
   */
  private String taskName;

  /**
   * 方法名称
   */
  private String methodName;

  /**
   * 表达式
   */
  private String cron;


  /**
   * 构建任务体
   *
   * @Param cron:任务表达式
   * @author peikunkun
   * @date 2020/11/3 0003 下午 2:27
   * @since
   */
  public static ScheduleInfo buildScheduleInfo(String scheduleInfoStr, String cron) {
    final ScheduleInfoBuilder builder = ScheduleInfo.builder();
    if (StringUtils.isBlank(scheduleInfoStr)) {
      return builder.build();
    }
    final int dividingLine = scheduleInfoStr.lastIndexOf(".");
    final String methodName = scheduleInfoStr.substring(dividingLine + 1);
    final String beanName = scheduleInfoStr.substring(0, dividingLine);
    if (StringUtils.isNotBlank(beanName)) {
      builder.taskName(beanName);
    }
    if (StringUtils.isNotBlank(methodName)) {
      builder.methodName(methodName);
    }
    if (StringUtils.isNotBlank(cron)) {
      builder.cron(cron);
    }
    return builder.build();
  }


  /**
   * 验证定时任务合法性
   *
   * @return boolean
   * @Param scheduleInfo
   * @author peikunkun
   * @date 2020/11/3 0003 下午 2:18
   * @since
   */
  public static boolean verifySchedule(ScheduleInfo scheduleInfo) {
    final String taskName = scheduleInfo.getTaskName();
    final String methodName = scheduleInfo.getMethodName();
    String cron = scheduleInfo.getCron();
    if (StringUtils.isBlank(taskName)) {
      log.error("【定时任务】-[任务详情]-定时任务未知的beanName:[{}]", JSONObject.toJSONString(scheduleInfo));
      return false;
    }
    if (StringUtils.isBlank(methodName)) {
      log.error("【定时任务】-[任务详情]-定时任务未知的methodName:[{}]", JSONObject.toJSONString(scheduleInfo));
      return false;
    }
    if (StringUtils.isBlank(cron) && !CronSequenceGenerator.isValidExpression(cron)) {
      log.error("【定时任务】-[任务详情]-定时任务未知/不合法的执行周期:[{}]", JSONObject.toJSONString(scheduleInfo));
      return false;
    }

    try {
      final Object bean = APPLICATIONCONTEXT.getBean(taskName);

      final Method method = bean.getClass().getMethod(methodName);
      return true;
    } catch (NoSuchMethodException e) {
      log.error("【定时任务】-[定时任务启动错误]-找不到方法(public):[{}.{}]", taskName, methodName, e);
    } catch (Exception e) {
      log.error("【定时任务】-[定时任务启动错误]-验证出现异常", e);
    }
    return false;
  }

}

